package com.yuke.cloud.service.uac.service.impl;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import com.yuke.cloud.common.base.constant.GlobalConstant;
import com.yuke.cloud.common.base.dto.LoginAuthDto;
import com.yuke.cloud.common.base.enums.ErrorCodeEnum;
import com.yuke.cloud.common.util.Collections3;
import com.yuke.cloud.common.util.PublicUtil;
import com.yuke.cloud.service.api.uac.exceptions.UacBizException;
import com.yuke.cloud.service.uac.dao.AccUserRoleMapper;
import com.yuke.cloud.service.uac.dto.*;
import com.yuke.cloud.service.uac.entity.AccRole;
import com.yuke.cloud.service.uac.entity.AccUser;
import com.yuke.cloud.service.uac.entity.AccUserRole;
import com.yuke.cloud.service.uac.service.AccRoleService;
import com.yuke.cloud.service.uac.service.AccUserRoleService;
import com.yuke.cloud.common.core.support.BaseService;
import com.yuke.cloud.service.uac.service.AccUserService;
import com.yuke.cloud.service.uac.vo.UserBindRoleVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;


/**
 * Created by wg on 2018/09/15.
 */
@Service
@Transactional
public class AccUserRoleServiceImpl extends BaseService<AccUserRole> implements AccUserRoleService {
    @Resource
    private AccUserRoleMapper accUserRoleMapper;

    @Resource
    private AccUserService accUserService;
    @Resource
    private AccRoleService accRoleService;

    //根据用户ID删除该用户对应的role
    public int deleteUserRoleByUserId(Long UserId) {
        Preconditions.checkArgument(UserId != null, "用户id为空");
        Preconditions.checkArgument(!Objects.equals(UserId, GlobalConstant.Sys.SUPER_MANAGER_USER_ID), "超级管理员角色不能删除");

        if (existRoleByUserId(UserId)) {
            Example example = new Example(AccUserRole.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("userId", UserId);
            return accUserRoleMapper.deleteByExample(example);
        }

        return 0;
    }

    //根据用户ID判断是否存在与角色绑定
    private Boolean existRoleByUserId(Long userId) {

        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userId", userId);
        int result = accUserRoleMapper.selectCountByExample(example);
        if (result > 0) {
            return true;
        } else {
            return false;
        }
    }

    public List<UserRoleDto> selectUserRoleInfoByUserId(Long userId) {
        return accUserRoleMapper.selectUserRoleInfoByUserId(userId);
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<Long> listSuperUser(Long superManagerRoleId) {
        if (superManagerRoleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        return accUserRoleMapper.listSuperUser(superManagerRoleId);
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<AccUserRole> listByRoleId(Long roleId) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId", roleId);

        return accUserRoleMapper.selectByExample(example);
    }

    @Override
    public void deleteByRoleId(Long roleId) {
        Preconditions.checkArgument(roleId != null, ErrorCodeEnum.UAC10012001.msg());
        Preconditions.checkArgument(!Objects.equals(roleId, GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID), "超级管理员角色不能删除");

        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId", roleId);
        int result = accUserRoleMapper.deleteByExample(example);
        if (result < 1) {
            throw new UacBizException(ErrorCodeEnum.UAC10012006, roleId);
        }
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<AccUserRole> listByRoleIdList(List<Long> idList) {
        if (PublicUtil.isEmpty(idList)) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }

        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("roleId", idList);

        return accUserRoleMapper.selectByExample(example);
    }

    @Override
    public void deleteByRoleIdList(List<Long> roleIdList) {
        Preconditions.checkArgument(PublicUtil.isNotEmpty(roleIdList), ErrorCodeEnum.UAC10012001.msg());
        Preconditions.checkArgument(!roleIdList.contains(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID), "超级管理员角色不能删除");

        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("roleId", roleIdList);
        int result = accUserRoleMapper.deleteByExample(example);
//        if (result < roleIdList.size()) {
//            throw new UacBizException(ErrorCodeEnum.UAC10012007, Joiner.on(GlobalConstant.Symbol.COMMA).join(roleIdList));
//        }
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public RoleBindUserDto getRoleBindUserDto(Long roleId, Long currentUserId) {
        RoleBindUserDto roleBindUserDto = new RoleBindUserDto();
        Set<Long> alreadyBindUserIdSet = Sets.newHashSet();
        AccRole accRole = accRoleService.getRoleById(roleId);
        if (PublicUtil.isEmpty(accRole)) {
            logger.error("找不到roleId={}, 的角色", roleId);
            throw new UacBizException(ErrorCodeEnum.UAC10012005, roleId);
        }

        // 查询所有用户包括已禁用的用户
        List<BindUserDto> bindUserDtoList;
        //todo 20200404 把供货商移除
       // if (GlobalConstant.Sys.SELLER_ROLE_ID == roleId || GlobalConstant.Sys.SUPPLIER_ROLE_ID == roleId) {
        if (GlobalConstant.Sys.SELLER_ROLE_ID == roleId ) {
            bindUserDtoList = accUserRoleMapper.selectAllNeedBindUserEx(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID, currentUserId);  // 供应商与商家用户只能通过申请绑定，不能直接处理
        } else {
            // mod by wg 20181220 超级管理员也可以对其他管理员进行角色绑定
            if (currentUserId == GlobalConstant.Sys.SUPER_MANAGER_USER_ID) {
                bindUserDtoList = accUserRoleMapper.selectAllNeedBindUserExAdmin(GlobalConstant.Sys.SUPER_MANAGER_USER_ID);
            }else {
                bindUserDtoList = accUserRoleMapper.selectAllNeedBindUser(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID, currentUserId/*, roleId*/);
            }
        }
        // 该角色已经绑定的用户
        List<AccUserRole> setAlreadyBindUserSet = this.listByRoleId(roleId);
        Set<BindUserDto> allUserSet = new HashSet<>(bindUserDtoList);

        for (AccUserRole accUserRole : setAlreadyBindUserSet) {
            alreadyBindUserIdSet.add(accUserRole.getUserId());
        }

        roleBindUserDto.setAllUserSet(allUserSet);
        roleBindUserDto.setAlreadyBindUserIdSet(alreadyBindUserIdSet);

        return roleBindUserDto;
    }

    @Override
    public void deleteExcludeSuperMng(Long roleId, Long superManagerRoleId) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        if (superManagerRoleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012004);
        }
        accUserRoleMapper.deleteExcludeSuperMng(roleId, superManagerRoleId);

    }

    @Override
    public int saveRoleUser(Long userId, Long roleId) {
        if (userId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10011001);
        }
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }

        AccUserRole userRole = new AccUserRole();
        userRole.setUserRoleId(generateId());
        userRole.setUserId(userId);
        userRole.setRoleId(roleId);
        return accUserRoleMapper.insertSelective(userRole);
    }

    @Override
    public void bindUser4Role(RoleBindUserReqDto roleBindUserReqDto, LoginAuthDto authResDto) {

        if (roleBindUserReqDto == null) {
            logger.error("参数不能为空");
            throw new IllegalArgumentException("参数不能为空");
        }

        Long roleId = roleBindUserReqDto.getRoleId();
        Long loginUserId = authResDto.getUserId();
        List<Long> userIdList = roleBindUserReqDto.getUserIdList();

        if (null == roleId) {
            throw new IllegalArgumentException(ErrorCodeEnum.UAC10012001.msg());
        }

        AccRole role = accRoleService.getRoleById(roleId);

        if (role == null) {
            logger.error("找不到角色信息 roleId={}", roleId);
            throw new UacBizException(ErrorCodeEnum.UAC10012005, roleId);
        }

        if (PublicUtil.isNotEmpty(userIdList) && userIdList.contains(loginUserId)) {
            logger.error("不能操作当前登录用户，已绑定的用户包含当前登录人loginUserId ={}", loginUserId);
            throw new UacBizException(ErrorCodeEnum.UAC10011023);
        }

        // 查询超级管理员用户Id集合
        List<Long> superUserList = this.listSuperUser(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID);
        List<Long> unionList = Collections3.intersection(userIdList, superUserList);

        // mod by wg 20181220 增加条件&& authResDto.getUserId() != GlobalConstant.Sys.SUPER_MANAGER_USER_ID，超级管理员可以对其他管理员操作
        if (PublicUtil.isNotEmpty(superUserList) && userIdList.contains(GlobalConstant.Sys.SUPER_MANAGER_USER_ID)) {
            logger.error("不能操作超级管理员用户1# 超级用户={}", superUserList);
            throw new UacBizException(ErrorCodeEnum.UAC10011023);
        }

        if (PublicUtil.isNotEmpty(userIdList) && PublicUtil.isNotEmpty(unionList)
                && authResDto.getUserId() != GlobalConstant.Sys.SUPER_MANAGER_USER_ID) {
            logger.error("不能操作超级管理员用户2# 超级用户={}", unionList);
            throw new UacBizException(ErrorCodeEnum.UAC10011023);
        }

        // 1. 先取消对该角色的用户绑定(不包含超级管理员用户)
        List<AccUserRole> userRoles = this.listByRoleId(roleId);

        if (PublicUtil.isNotEmpty(userRoles)) {
            this.deleteExcludeSuperMng(roleId, GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID);
        }

        if (PublicUtil.isEmpty(userIdList)) {
            // 取消该角色的所有用户的绑定
            logger.info("取消绑定所有非超级管理员用户成功");
            return;
        }

        // 绑定所选用户
        for (Long userId : userIdList) {
            AccUser uacUser = accUserService.queryByUserId(userId);
            if (PublicUtil.isEmpty(uacUser)) {
                logger.error("找不到绑定的用户 userId={}", userId);
                throw new UacBizException(ErrorCodeEnum.UAC10011024, userId);
            }
            this.saveRoleUser(userId, roleId);
        }

    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public AccUserRole getByUserIdAndRoleId(Long userId, Long roleId) {

        AccUserRole accUserRole = null;

        if (null == userId) {
            throw new UacBizException(ErrorCodeEnum.UAC10011001);
        }

        if (null == roleId) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }

        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId", roleId).andEqualTo("userId", userId);

        List<AccUserRole> list = accUserRoleMapper.selectByExample(example);

        if (list.size() > 0) {
            accUserRole = list.get(0);
        }

        return accUserRole;
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public UserBindRoleVo getUserBindRoleDto(Long userId) {
        UserBindRoleVo userBindRoleVo = new UserBindRoleVo();
        Set<Long> alreadyBindRoleIdSet = Sets.newHashSet();
        AccUser accUser = accUserService.queryByUserId(userId);
        if (accUser == null) {
            logger.error("找不到userId={}, 的用户", userId);
            throw new UacBizException(ErrorCodeEnum.UAC10011003, userId);
        }

        // 查询所有角色包括该用户拥有的角色
        // mod by wg 20181220 改成超级管理角色也可以绑定给用户
//        List<BindRoleDto> bindRoleDtoList = accUserRoleMapper.selectAllNeedBindRole(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID);
        List<BindRoleDto> bindRoleDtoList = accUserRoleMapper.selectAllNeedBindRoleEx();

        // 该角色已经绑定的用户
        List<AccUserRole> setAlreadyBindRoleSet = accUserRoleMapper.listByUserId(userId);

        Set<BindRoleDto> allUserSet = new HashSet<>(bindRoleDtoList);

        for (AccUserRole accUserRole : setAlreadyBindRoleSet) {
            alreadyBindRoleIdSet.add(accUserRole.getRoleId());
        }

        userBindRoleVo.setAllRoleSet(allUserSet);
        userBindRoleVo.setAlreadyBindRoleIdSet(alreadyBindRoleIdSet);

        return userBindRoleVo;
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<AccUserRole> listByUserId(Long userId) {
        if (userId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10011001);
        }
        return accUserRoleMapper.listByUserId(userId);
    }

    @Override
    public int deleteByUserId(Long userId) {
        if (null == userId) {
            throw new UacBizException(ErrorCodeEnum.UAC10011001);
        }

        AccUserRole param = new AccUserRole();
        param.setUserId(userId);
        return accUserRoleMapper.delete(param);
    }

    @Override
    public void bindUserRoles(BindUserRolesDto bindUserRolesDto, LoginAuthDto authResDto) {

        if (bindUserRolesDto == null) {
            logger.error("参数不能为空");
            throw new IllegalArgumentException("参数不能为空");
        }

        Long operUserId = bindUserRolesDto.getUserId();
        Long loginUserId = authResDto.getUserId();
        List<Long> roleIdList = bindUserRolesDto.getRoleIdList();

        if (null == operUserId) {
            throw new UacBizException(ErrorCodeEnum.UAC10011001);
        }

        // 任何用户不能操作admin用户
        if (Objects.equals(operUserId, GlobalConstant.Sys.SUPER_MANAGER_USER_ID)) {
            throw new UacBizException(ErrorCodeEnum.UAC10011034);
        }

        AccUser user = accUserService.queryByUserId(operUserId);

        if (user == null) {
            logger.error("找不到用户信息 operUserId={}", operUserId);
            throw new UacBizException(ErrorCodeEnum.UAC10011003, operUserId);
        }

        // mod by wg 20181220，增加GlobalConstant.Sys.SUPER_MANAGER_USER_ID != loginUserId 条件
        if (GlobalConstant.Sys.SUPER_MANAGER_USER_ID != loginUserId
                && (PublicUtil.isNotEmpty(roleIdList) && roleIdList.contains(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID))) {
            logger.error("操作超级管理员角色 userId={}", loginUserId);
            throw new UacBizException(ErrorCodeEnum.UAC10011023);
        }

        // 1. 先取消对该角色的用户绑定(不包含超级管理员用户)
        List<AccUserRole> userRoles = this.listByUserId(operUserId);

        if (PublicUtil.isNotEmpty(userRoles)) {
            this.deleteByUserId(operUserId);
        }

        // 更新用户的操作时间
        final AccUser updateUser = new AccUser();
        updateUser.setUserId(operUserId);
        updateUser.setUpdateTime(new Date());
        accUserService.updateUser(updateUser);

        if (PublicUtil.isEmpty(roleIdList)) {
            // 取消该角色的所有用户的绑定
            logger.info("绑定角色成功");
            return;
        }

        // 绑定所选用户
        for (Long roleId : roleIdList) {
            AccRole accRole = accRoleService.getRoleById(roleId);
            if (accRole == null) {
                logger.error("找不到绑定的角色. roleId={}", roleId);
                throw new UacBizException(ErrorCodeEnum.UAC10012008, roleId);
            }
            this.saveRoleUser(operUserId, roleId);
        }
    }

    /**
     * 判断某一个用户是否是超级管理员角色
     * @return
     */
    @Override
    public Boolean checkAdminByUserId(Long userId) {
        Preconditions.checkArgument(userId != null, "用户id为空");

        int count;

        Example example = new Example(AccUserRole.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userId", userId).andEqualTo("roleId", GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID);
        count = accUserRoleMapper.selectCountByExample(example);

        return (count > 0);
    }

    @Override
    public Boolean checkAdminByLoginName(String loginName) {
        Preconditions.checkArgument(loginName != null, "用户账号为空");

        Integer count = accUserRoleMapper.checkAdminRoleByLoginName(GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID, loginName);

        return (count > 0);
    }

    @Override
    public Long generateUserRoleId() {
        return generateId();
    }
}
